package workers

import (
	"context"
	"fmt"
	"gitee.com/captials-team/ubdframe/src/common"
	"gitee.com/captials-team/ubdframe/src/pkg/contexts"
	"gitee.com/captials-team/ubdframe/src/pkg/jobworker"
	v1log "gitee.com/captials-team/ubdframe/src/pkg/logs"
	"gitee.com/captials-team/ubdframe/src/pkg/metrics"
	"go.uber.org/dig"
	"os"
	"time"
)

// FastUseWorker 快速上手使用的worker
type FastUseWorker struct {
	di        *dig.Container
	op        *jobworker.JobParam
	l         v1log.ILog
	monitorCh chan metrics.IndicData
	ctx       *contexts.AdvancedContext
}

func NewFastUseWorker(di *dig.Container, op *jobworker.JobParam) jobworker.IWorker {
	w := &FastUseWorker{
		di:  di,
		op:  op,
		l:   v1log.NewWriterLog(os.Stdout, 0),
		ctx: contexts.NewCancelAdvancedContext(context.Background()),
	}
	if di != nil {
		common.ErrPanic(di.Invoke(func(l v1log.ILog) {
			w.l = l
		}))
	}

	return w
}

func (w *FastUseWorker) Name() string {
	return w.op.Action
}

func (w *FastUseWorker) Op() *jobworker.JobParam {
	return w.op
}

func (w *FastUseWorker) Actions() []string {
	return []string{}
}

func (w *FastUseWorker) Params() map[string]string {
	return nil
}

func (w *FastUseWorker) Start() {
	w.TimedStart(func() (goon bool) {
		w.l.Info(" %s running", w.op.OpId)

		return true
	})
}

// Run 运行指定次数
func (w *FastUseWorker) Run(count int64) {
	w.l.Warn("not support run [%s] times %d", w.Op().Action, count)
}

func (w *FastUseWorker) Stop() {
	w.ctx.Cancel(nil)
	w.ctx.Wait.Wait()
}

func (w *FastUseWorker) Interval() time.Duration { //设置运行的间隔
	if w.op.Interval > 0 {
		return w.op.Interval
	}
	return time.Second
}

func (w *FastUseWorker) GetRunInterval() time.Duration { //实际运行的间隔
	return time.Second
}

// Tps 总tps
func (w *FastUseWorker) Tps() float64 {
	return 0
}

// Log 提供的日志
func (w *FastUseWorker) Log() v1log.ILog {
	return w.l
}

func (w *FastUseWorker) Debug() {

}

// TimedStart 定时执行开始
func (w *FastUseWorker) TimedStart(f func() (goon bool)) {
	w.ctx.Wait.Add(1)
	defer w.ctx.Wait.Done()

	if w.op == nil {
		panic(fmt.Sprintf("%s op nil", w.Name()))
	}

	ti := time.NewTicker(time.Second)
	if w.op.Interval > 0 {
		ti = time.NewTicker(w.op.Interval)
	}
	i := 0

	for {
		i++
		select {
		case <-w.ctx.Done():
			return
		case <-ti.C:
			if !f() {
				return
			}
		}
	}
}

func (w *FastUseWorker) Monitor(data metrics.IndicData) {
	if w.monitorCh != nil {
		w.monitorCh <- data
	} else {
		w.l.Info("monitor ch is nil")
	}
}

func (w *FastUseWorker) monitor(data metrics.IndicData) {
	if w.monitorCh != nil {
		w.monitorCh <- data
	} else {
		w.l.Info("monitor ch is nil")
	}
}

func (w *FastUseWorker) SetMonitor(ch chan metrics.IndicData) {
	w.monitorCh = ch
}

func (w *FastUseWorker) Ctx() *contexts.AdvancedContext {
	return w.ctx
}
